/**
  * @file       network.c
  * @brief      网络组件，处理mqtt和http
  * @copyright  Copyright (c) 2020~2030 ShenZhen Dxtc Tech. Co., Ltd.
  * All rights reserved.
  * @version    V1.0
  * @author     TianXubin
  * @date       2021-11-11 16:38:37
  * @note       鼎新同创·智能锁
  *
  *****************************************************************************/

#include "network.h"
#include "component.h"
#include "device.h"

#define NETWORK_LOG(format, ...) OSAL_LOG(C_PURPLE format C_NONE, ##__VA_ARGS__)

#define VHW_NETWORK vNETWORK_0 //virtual hardware interface

#define MAX_QUEUE_MSG_LEN 10
static SuperQueueHandle_t qNetworkHandle = NULL;

/**
  * @brief  发布消息
  * @note   
  * @param  *data：消息内容
  * @param  len：消息长度
  * @return void
  */
void Network_MessagePushlish(void *msg, uint16_t len)
{
    NETWORK_LOG("Network_MessagePushlish(type: %d, len: %d)\r\n", ((uint8_t *)msg)[0], len);
    OSAL_MessagePublish(msg, len);
}

/**
  * @brief  处理接收到的邮箱数据
  * @note   
  * @param  *msg: 消息内容
  * @return void
  */
static void Network_ProcessMbox(void *msg, uint16_t len)
{
    uint8_t msg_type = ((uint8_t *)msg)[0];
    NETWORK_LOG("recv network mbox msg type: %d, len: %d\r\n", msg_type, len);

    if (msg_type == NETWORK_CTRL_GET_DFU_DATA) //获取固件升级数据
    {
        FirmwareData_t *read_data = &((uint8_t *)msg)[2];

        uint32_t send_len = sizeof(NetworkMsg_t) + sizeof(FirmwareData_t) + read_data->data_len;
        NetworkMsg_t *send_msg = OSAL_Malloc(send_len);

        send_msg->msg_type = NETWORK_MSG_FW_DATA;
        memcpy(send_msg->fw_data, read_data, sizeof(FirmwareData_t));
        Device_Read(VHW_NETWORK, send_msg->fw_data->data, read_data->data_len, read_data->psn); //读取固件数据
        Network_MessagePushlish(send_msg, send_len);
        OSAL_Free(send_msg);
    }
    else //其它消息全部转给驱动层处理
    {
        void *data = (len > 1) ? &(((uint8_t *)msg)[1]) : NULL;
        if(msg_type == NETWORK_CTRL_MQTT_CONNECT)
        {
            OSAL_SetTaskStatus(TASK_STA_ACTIVE);
            NETWORK_LOG("\r\nSet network task active\r\n");
        }
        Device_Write(VHW_NETWORK, data, len - 1, msg_type);

    }
}

/**
  * @brief  解析接受到的消息
  * @note   
  * @param  
  * @return void
  */
void Network_ParseRxPacket(void)
{
    uint16_t len = 0;
    while (OSAL_QueueLenght(qNetworkHandle, &len))
    {
        NetworkMsg_t *msg = (NetworkMsg_t*)OSAL_Malloc(len);
        if (msg != NULL)
        {
            memset(msg, 0, len);
            len = OSAL_QueueReceive(qNetworkHandle, msg);
            if(msg->msg_type == NETWORK_MSG_MQTT_OFFLINE || msg->msg_type == NETWORK_MSG_MQTT_ONLINE)
            {
                OSAL_SetTaskStatus(TASK_STA_NORMAL);
            }
            Network_MessagePushlish(msg, len);
            OSAL_Free(msg);
        }
    }
}

/**
  * @brief  中断处理
  * @note   
  * @param  *pBuf：消息内容
  * @param  len：数据长度
  * @return 
  */
static void Network_Irq_Handler(VirtualHardware_enum_t dev, void *pBuf, uint32_t len)
{
    uint8_t msg_type = (len >> 16) & 0xff;
    uint16_t msg_len = (len & 0xffff) + 1;
    uint8_t *msg = OSAL_Malloc(msg_len);
    if (msg)
    {
        msg[0] = msg_type; //首字节作为消息类型来区分
        memcpy(&msg[1], (uint8_t *)pBuf, (msg_len-1));
        OSAL_QueueSendToBack(qNetworkHandle, (void *)msg, msg_len);
        OSAL_Free(msg);

        OSAL_EventCreateFromISR(COMP_NETWORK);
    }
}

static void Network_Init(void)
{
    NETWORK_LOG("network Init\r\n");
    if (qNetworkHandle == NULL)
    {
        qNetworkHandle = OSAL_QueueCreate(MAX_QUEUE_MSG_LEN);
        /* 注册中断回调 */
        Device_RegisteredCB(VHW_NETWORK, Network_Irq_Handler);
    }
}

/**
  * @brief  网络任务函数
  *
  * @note
  *
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Network_Task(uint32_t event)
{
    /* 系统启动事件 */
    if (event & EVENT_SYS_START)
    {
        NETWORK_LOG("network task start\r\n");
        Network_Init();
        return (event ^ EVENT_SYS_START);
    }

    /* 系统邮箱事件 */
    if (event & EVENT_SYS_MBOX)
    {
        uint16_t len = 0;
        while (OSAL_MboxLenght(&len))
        {
            void *buffer = OSAL_Malloc(len);
            if (buffer)
            {
                OSAL_MboxAccept(buffer);
                Network_ProcessMbox(buffer, len);
                OSAL_Free(buffer);
            }
        }
        return (event ^ EVENT_SYS_MBOX);
    }

    /* 中断事件 */
    if (event & EVENT_SYS_ISR)
    {
        NETWORK_LOG("NETWORK ISR EVENT\r\n");
        Network_ParseRxPacket();
        return (event ^ EVENT_SYS_ISR);
    }

    return 0;
}

COMPONENT_TASK_EXPORT(COMP_NETWORK, Network_Task, 0);

//! network组件  ---->  底层驱动
// 1、连接mqtt服务器
// MqttConnectInfo_stu_t sever;
// Device_Write(vNETWORK_0, &sever, sizeof(sever), NETWORK_CTRL_MQTT_CONNECT);

// 2、断开mqtt服务器
// Device_Write(vNETWORK_0, NULL, 0, NETWORK_CTRL_MQTT_DISCONNECT);

// 3、mqtt-publish
// MqttData_t data;
// Device_Write(vNETWORK_0, &data, sizeof(data)+len, NETWORK_CTRL_MQTT_SEND);

// 4、http-download
// url[0] : 第0个字节是devNum
// url[1~n] : 下载链接
// Device_Write(vNETWORK_0, url, len, NETWORK_CTRL_HTTP_DOWNLOAD);

// 5、读取已下载的固件数据
// uint8_t *buffer = OSAL_Malloc(len);
// n = Device_Read(vFLASH_3, buffer, len, psn); //psn表示读第n包数据
// n:表示实际读取到的数据，len表示想要读取的数据长度

//! network组件  <----  底层驱动
// 1、mqtt连接状态改变callback
// MqttStatus_enum_t status = MQTT_ONLINE;
// Device_IRQHandler(vNETWORK_0, &status, (NETWORK_MSG_MQTT_STATUS << 16) | 1);

// 2、mqtt数据接收callback
// MqttData_t mqtt;
// Device_IRQHandler(vNETWORK_0, &mqtt, (NETWORK_MSG_MQTT_RECV << 16) | len);

// 3、http下载状态改变callback
// HttpDlStatus_stu_t dl_status = {HTTP_DL_SUCCESS, devNum};
// Device_IRQHandler(vNETWORK_0, &dl_status, (NETWORK_MSG_HTTP_STATUS << 16) | 1);

/* Won't be used but necessary for forcing the linker to import this file */
char import_kos_network;
